package com.yx.changdao.web.handler;

import com.yx.changdao.common.data.RespCodeEnum;
import com.yx.changdao.common.data.Result;
import com.yx.changdao.common.data.ResultCodeEnum;
import com.yx.changdao.common.exception.AlertException;
import com.yx.changdao.common.utils.SpringContextUtils;
import com.yx.changdao.common.utils.SysConst;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.nutz.lang.Strings;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * @Description: 统一异常处理类
 * @Auther: Zhangjiashun
 * @create 2019/10/18 11:51
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理特定异常
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public Result error(BadSqlGrammarException e) {
        this.outErrorLog(e);
        return Result.error("错误的SQL语句");
    }

    @ExceptionHandler(BindException.class)
    public Result error(BindException e) {
        ObjectError objectError = e.getAllErrors().get(0);
        return Result.error(RespCodeEnum.BAD_REQUEST, objectError.getDefaultMessage());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result error(HttpMessageNotReadableException e) {
        this.outErrorLog(e);
        return Result.error("Json解析异常");
    }

    @ExceptionHandler({UnauthorizedException.class})
    public Result error(UnauthorizedException e) {
        this.outErrorLog(e);
        return Result.error(RespCodeEnum.NO_PERMISSION, String.format("权限不足[%s]", e.getMessage()));
    }

    @ExceptionHandler({UnauthenticatedException.class})
    public Result error(UnauthenticatedException e) {
        this.outErrorLog(e);
        return Result.error(RespCodeEnum.UNAUTHORIZED, "用户认证失败");
    }

    @ExceptionHandler({AuthenticationException.class})
    public Result error(AuthenticationException e) {
        this.outErrorLog(e);
        return Result.error(RespCodeEnum.UNAUTHORIZED, "用户认证失败");
    }

    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result error(HttpRequestMethodNotSupportedException e) {

        return Result.error(RespCodeEnum.METHOD_NOT_ALLOWED, "不支持的" + e.getMethod() + "请求方式");
    }

    @ExceptionHandler(AlertException.class)
    public Result error(AlertException e) {
        this.outErrorLog(e);
        return Result.error(RespCodeEnum.BAD_REQUEST, e.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    public Result error(Exception e) {
        this.outErrorLog(e);

       if(Strings.isNotBlank(e.getMessage())){
           return Result.error(e.getMessage());
       }else{
           return Result.error(ResultCodeEnum.UNKNOWN_REASON.getMessage());
       }

    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result valid(MethodArgumentNotValidException e) {
        StringBuffer buffer = new StringBuffer();
        BindingResult result  = e.getBindingResult();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            errors.forEach(p ->{
                FieldError fieldError = (FieldError) p;
                buffer.append(fieldError.getDefaultMessage()).append(",");
            });
        }
        return Result.error(RespCodeEnum.BAD_REQUEST, buffer.toString());
    }


    /**
     * 输出错误日志
     *
     * @param e 错误
     */
    private void outErrorLog(Exception e) {
        String active = SpringContextUtils.getAppConfig("spring.profiles.active", "");
        if (StringUtils.equals(active, SysConst.DEV)) {
            log.error(ExceptionUtils.getStackTrace(e));
        } else if (StringUtils.equals(active, SysConst.PRO)) {
            // 正式环境日志写入异常信息 正式上线之前写入堆栈
            log.error(ExceptionUtils.getStackTrace(e));
            // log.error(ExceptionUtils.getMessage(e));
        } else {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }
}
